package com.base.dynamicprograming;

/**
 * @ClassName: FibNumber
 * @Description: 509. 斐波那契数
 *
 * @author: li
 * @Date: 2021/8/19 6:43 下午
 */
public class FibNumber {
    public int fib(int n) {
        /**
         * 递归实现
         */
        if (n == 0 || n == 1) {
            return n;
        } else {
            return fib(n - 1) + fib(n - 2);
        }

    }

    public int fib1(int n){
        /**
         * 带备忘录的递归实现
         */
        // 存放计算结果的数组
        int[] memo = new int[n+1];
        //由于0影响判断，单独计算
        if (n == 0){
            return n;
        }
        return helper(memo,n);

    }

    public int helper(int[] memo, int n){
        /**
         * 自顶向下递归调用，将中途算出来的结果保存到备忘录中，
         * 同时，如果在计算中，存在备忘录的值，优先取备忘录里面的值。
         */
        //  递归的基本问题
        if (n == 1 || n == 2) return 1;
        //当备忘录有值时，直接返回备忘录的值
        if(memo[n]!=0){
            return memo[n];
        }
        // 保存计算结果
        memo[n] = helper(memo,n-1) + helper(memo, n-2);
        return memo[n];

    }
    public int fib2(int n){
        /**
         * 迭代法，自底向上动态规划（实际上不算动态规划）
         */
        if (n<2){
            return n;
        }
        int q = 0,p = 0,r = 1;
        for (int i = 2; i <= n; i++) {
            // 滑动数组
            q = p;
            p = r;
            r = q + p;
        }

        return r;

    }

    public int fib3(int n){
        /**
         * 带dp表的动态规划
         */
        if (n==0){
            return 0;
        }
        // 0位置空着不用,dp表
        int[] dp = new int[n+1];
        dp[1] = dp[2] = 1;
        for (int i = 3; i <= n; i++) {
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[n];
    }
}
